import React, { FC, Key } from 'react';
import { Tree, Input } from 'antd';
import type { TreeDataType, TreeDataItemType } from './data.d';
import { DataNode, EventDataNode } from 'antd/lib/tree';

const { Search } = Input;

type SearchTreePropsType = {
  treeData?: TreeDataType;
  changeKey?: any;
  checkedId?: string;
};

const SearchTree: FC<SearchTreePropsType> = ({
  treeData,
  changeKey,
  checkedId,
}) => {
  // 展开指定的树节点
  const [expandedKeys, setExpandedKeys] = React.useState<string[]>([]);
  // 搜索框内容
  const [searchValue, setSearchValue] = React.useState<string>('');
  // 控制父节点的展开
  const [autoExpandParent, setAutoExpandParent] = React.useState<boolean>(true);
  // 全部数据同级储存
  const [dataLists, setDataLists] = React.useState<TreeDataType | []>([]);

  React.useEffect(() => {
    let dataList: TreeDataType = [];
    // 将所有项整合到同级
    generateList(dataList, treeData);
    setDataLists(dataList);
  }, []);

  // 将所有项整合到同级
  const generateList = (dataList: TreeDataType, data?: TreeDataType) => {
    if (data) {
      for (let i = 0; i < data.length; i++) {
        const node = data[i];
        const { key, title } = node;
        dataList.push({ key, title });
        if (node.children) {
          generateList(dataList, node.children);
        }
      }
    }
  };

  // 展开/收起节点时触发
  const onExpand = (expandedKeys: any[]) => {
    setExpandedKeys(expandedKeys);
    setAutoExpandParent(false);
  };

  // 查找父级节点
  const getParentKey: (
    key: string,
    tree?: TreeDataType,
  ) => string | undefined = (key: string, tree?: TreeDataType) => {
    let parentKey;
    if (tree) {
      for (let i = 0; i < tree.length; i++) {
        const node = tree[i];
        if (node.children) {
          if (node.children.some((item) => item.key === key)) {
            parentKey = node.key;
          } else if (getParentKey(key, node.children)) {
            parentKey = getParentKey(key, node.children);
          }
        }
      }
    }
    return parentKey;
  };

  // 搜索输入框内容改变时调用
  const onChange = (e: any) => {
    const { value } = e.target; // 获取输入框内容
    // 筛选包含输入内容的项 返回其父级key值
    let expandedKeys = dataLists
      .map((item) => {
        if (item.title.indexOf(value) > -1) {
          return getParentKey(item.key, treeData);
        }
        return '';
      })
      .filter((item, i, self) => item && self.indexOf(item) === i);
    setExpandedKeys(value ? expandedKeys : []);
    setSearchValue(value);
    setAutoExpandParent(true);
  };

  // 搜索时改变树的渲染
  const loop = (data?: any) =>
    data?.map((item: TreeDataItemType) => {
      // 返回搜索内容的 下标
      const index = item.title.indexOf(searchValue);
      // 搜索内容之前的标题
      const beforeStr = item.title.substr(0, index);
      // 搜索内容之后的标题
      const afterStr = item.title.substr(index + searchValue.length);
      // 重新定义标题
      const title =
        index > -1 ? (
          <span>
            {beforeStr}
            <span style={{ color: 'red' }}>{searchValue}</span>
            {afterStr}
          </span>
        ) : (
          <span>{item.title}</span>
        );
      if (item.children) {
        return { title, key: item.key, children: loop(item.children) };
      }
      return {
        title,
        key: item.key,
      };
    });

  // 选择树节点时调用
  const onSelect:
    | ((
        selectedKeys: Key[],
        info: {
          event: 'select';
          selected: boolean;
          node: EventDataNode;
          selectedNodes: DataNode[];
          nativeEvent: MouseEvent;
        },
      ) => void)
    | undefined = (selectedKeys: Key[]) => {
    changeKey(selectedKeys[0]);
  };

  return (
    <div>
      <Search
        style={{ marginBottom: 8 }}
        placeholder="Search"
        onChange={onChange}
      />
      <Tree
        selectedKeys={checkedId ? [checkedId] : []}
        // 展开/收起节点时触发
        onExpand={onExpand}
        // 展开指定的树节点
        expandedKeys={expandedKeys}
        // 是否自动展开父节点
        autoExpandParent={autoExpandParent}
        // 树数据
        treeData={loop(treeData)}
        // 选择树节点时调用
        onSelect={onSelect}
      />
    </div>
  );
};

export default SearchTree;
